package com.wpen.unit.service.impl;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.springframework.stereotype.Service;

import com.wpen.unit.core.cache.TaskExecContext;
import com.wpen.unit.core.cache.TaskExecProcess;
import com.wpen.unit.core.cache.TaskFutureTask;
import com.wpen.unit.core.pool.ExecThreadPool;
import com.wpen.unit.core.pool.TaskExecRunner;
import com.wpen.unit.enums.ExecStatus;
import com.wpen.unit.service.AgentService;
import com.wpen.unit.web.WebVariables;
import com.wpen.unit.web.dto.ContextRequest;
import com.wpen.unit.web.dto.ContextResponse;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * 
 * 
 * @author Wang Peng
 * @date 2022-12-04
 */
@Service
@Slf4j
public class AgentServiceImpl implements AgentService {

	@Override
	public ContextResponse startTask(ContextRequest contextRequest) {
		TaskExecContext taskExecContext = dto2do(contextRequest);
		String key = taskExecContext.getKey();
		// 创建执行线程
		TaskExecRunner taskExecRunner = new TaskExecRunner(taskExecContext);
		FutureTask<TaskExecContext> futureTask = new FutureTask<>(taskExecRunner);
		// 将任务加入到本地缓存Cache记录里面
		TaskFutureTask.getInstance().putFutureTask(key, futureTask);
		// 执行任务
		ExecThreadPool.getInstance().execute(futureTask);
		// 返回
		ContextResponse contextResponse = new ContextResponse();
		try {
			TaskExecContext taskRunStatus = futureTask.get(50, TimeUnit.MILLISECONDS);
			// 这个地方如果能获取到，，肯定是子线程抛异常了
			contextResponse.setStatus(taskRunStatus.getStatus().value());
			contextResponse.setExitValue(taskRunStatus.getExitValue());
			contextResponse.setCode(taskRunStatus.getRtnCode());
			contextResponse.setMsg(taskRunStatus.getRtnMsg());
			contextResponse.setErrors(taskRunStatus.getErrors());
			contextResponse.setStartDate(taskRunStatus.getStartDate());
			contextResponse.setEndDate(taskRunStatus.getEndDate());
		} catch (TimeoutException e) {
			contextResponse.setMsg("线程执行中：[" + key + "]");
		} catch (Exception e) {
			// 其他异常不处理，交给检测接口
			// 异常吃掉
		}
		return contextResponse;
	}

//    @Override
//    public ContextResponse stopTask(ContextRequest contextRequest) {
//        // TODO Auto-generated method stub
//        return null;
//    }

	@Override
	public ContextResponse checkTask(ContextRequest contextRequest) {
		TaskExecContext taskExecContext = dto2do(contextRequest);
		String key = taskExecContext.getKey();

		ContextResponse contextResponse = new ContextResponse();

		FutureTask<TaskExecContext> futureTask = TaskFutureTask.getInstance().getFutureTask(key);
		if (futureTask == null) {
			contextResponse.setCode(WebVariables.RESPONSE_AGENT_NOTFOUND);
			contextResponse.setMsg("任务作业[" + key + "]没有找到");
			return contextResponse;
		}
		try {
			TaskExecContext taskRunStatus = futureTask.get(100, TimeUnit.MILLISECONDS);
			contextResponse.setStatus(taskRunStatus.getStatus().value());
			contextResponse.setExitValue(taskRunStatus.getExitValue());
			contextResponse.setCode(taskRunStatus.getRtnCode());
			contextResponse.setMsg(taskRunStatus.getRtnMsg());
			contextResponse.setErrors(taskRunStatus.getErrors());
			contextResponse.setStartDate(taskRunStatus.getStartDate());
			contextResponse.setEndDate(taskRunStatus.getEndDate());
		} catch (InterruptedException e) {
			log.error("检测中断异常", e);
			contextResponse.setCode(WebVariables.RESPONSE_AGENT_UNKOWN);
			contextResponse.setMsg("线程中断：[" + key + "]");
		} catch (ExecutionException e) {
			log.error("检测异常", e);
			contextResponse.setCode(WebVariables.RESPONSE_AGENT_UNKOWN);
			contextResponse.setMsg("线程执行出错：[" + key + "]");
		} catch (TimeoutException e) {
			contextResponse.setCode(WebVariables.RESPONSE_AGENT_RNNNING);
			contextResponse.setMsg("线程执行中：[" + key + "]");
		}
		return contextResponse;
	}

	@Override
	public ContextResponse removeTask(ContextRequest contextRequest) {
		TaskExecContext taskExecContext = dto2do(contextRequest);
		String key = taskExecContext.getKey();
		TaskFutureTask.getInstance().removeFutureTask(key);
		ContextResponse contextResponse = new ContextResponse();
		return contextResponse;
	}

	@Override
	public ContextResponse killProcess(ContextRequest contextRequest) {
		TaskExecContext taskExecContext = dto2do(contextRequest);
		String key = taskExecContext.getKey();

		ContextResponse contextResponse = new ContextResponse();
		contextResponse.setExitValue(1);
		contextResponse.setStatus(ExecStatus.Excption.value());
		contextResponse.setCode(WebVariables.RESPONSE_AGENT_EXCEPTION);
		contextResponse.setMsg("用户终止: 任务作业[" + key + "]异常终止");
		try {
			Process process = TaskExecProcess.getInstance().getProcess(key);
			if (process != null && process.isAlive()) {
				process.destroy();
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		FutureTask<TaskExecContext> futureTask = TaskFutureTask.getInstance().getFutureTask(key);
		if (futureTask != null) {
			try {
				TaskExecContext taskRunStatus = futureTask.get(20, TimeUnit.MILLISECONDS);
				taskRunStatus.setExitValue(1);
				taskRunStatus.setStatus(ExecStatus.Excption);
				taskRunStatus.setRtnCode(WebVariables.RESPONSE_AGENT_EXCEPTION);
				taskRunStatus.setRtnMsg("用户终止: 任务作业[" + taskRunStatus.getKey() + "]异常终止");
				
				contextResponse.setStatus(taskRunStatus.getStatus().value());
				contextResponse.setExitValue(taskRunStatus.getExitValue());
				contextResponse.setCode(taskRunStatus.getRtnCode());
				contextResponse.setMsg(taskRunStatus.getRtnMsg());
				contextResponse.setErrors(taskRunStatus.getErrors());
				contextResponse.setStartDate(taskRunStatus.getStartDate());
				contextResponse.setEndDate(taskRunStatus.getEndDate());
                
			} catch (Exception e) {
			}
		}
		return contextResponse;
	}

	private TaskExecContext dto2do(ContextRequest contextRequest) {
		TaskExecContext taskExecContext = new TaskExecContext();
		taskExecContext.setBizCode(contextRequest.getBizCode());
		taskExecContext.setBatchCode(contextRequest.getBatchCode());
		taskExecContext.setTaskCode(contextRequest.getTaskCode());
		taskExecContext.setTaskId(contextRequest.getTaskId());
		taskExecContext.setJobId(contextRequest.getJobId());
		taskExecContext.setAcctDate(contextRequest.getAcctDate());
		taskExecContext.setParams(contextRequest.getParams());
		taskExecContext.setCmd(contextRequest.getCmd());
		return taskExecContext;
	}

}
